package com.cf.oss.core;

/**
 * game-server-OSSService
 *
 * @author <a href="2428922347@qq.com">Zhu mingming</a>
 * @info
 * @since 2018/6/5 下午 12:02
 */

import com.aliyun.oss.OSSClient;
import com.aliyun.oss.model.UploadFileRequest;
import com.aliyun.oss.model.UploadFileResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

public class OSSService implements OSSOperations {
    private static final Logger log = LoggerFactory.getLogger(OSSService.class);
    private final OSSConfig ossConfig;
    private final ThreadLocal<OSSClient> ossClientContext = new ThreadLocal();

    public OSSService(OSSConfig ossConfig) {
        Assert.notNull(ossConfig, "Parameter 'ossConfig' must not be null.");
        this.ossConfig = ossConfig;
    }

    public UploadFileResult uploadFile(UploadFileRequest uploadFileRequest) {
        Assert.notNull(uploadFileRequest, "Parameter 'uploadFileRequest' must not be null.");
        return (UploadFileResult) this.invoke(uploadFileRequest, new OSSFunction<UploadFileRequest, UploadFileResult>() {
            public UploadFileResult apply(UploadFileRequest request, OSSClient ossClient) throws Throwable {
                return ossClient.uploadFile(request);
            }
        });
    }

    public OSSBatchResult<UploadFileRequest, UploadFileResult> uploadFile(List<UploadFileRequest> uploadFileRequests) {
        Assert.notEmpty(uploadFileRequests, "Parameter 'uploadFileRequests' must not be empty.");
        return (OSSBatchResult) this.invoke(uploadFileRequests, new OSSFunction<List<UploadFileRequest>, OSSBatchResult<UploadFileRequest, UploadFileResult>>() {
            public OSSBatchResult<UploadFileRequest, UploadFileResult> apply(List<UploadFileRequest> request, OSSClient ossClient) throws Throwable {
                OSSBatchResult<UploadFileRequest, UploadFileResult> results = new OSSBatchResult();
                Iterator var4 = request.iterator();

                while (var4.hasNext()) {
                    UploadFileRequest uploadFileRequest = (UploadFileRequest) var4.next();
                    if (uploadFileRequest != null) {
                        try {
                            UploadFileResult uploadFileResponse = ossClient.uploadFile(uploadFileRequest);
                            results.addSuccessOne(uploadFileRequest, uploadFileResponse);
                        } catch (Throwable var7) {
                            OSSService.log.error("Aliyun oss client upload file: {} cause an error", uploadFileRequest, var7);
                            results.addFailedOne(uploadFileRequest);
                        }
                    }
                }

                return results;
            }
        });
    }

    public OSSBatchResult<UploadFileRequest, UploadFileResult> uploadFile(UploadFileRequest... uploadFileRequests) {
        Assert.notNull(uploadFileRequests, "Parameter 'uploadFileRequests' must not be null.");
        return this.uploadFile(Arrays.asList(uploadFileRequests));
    }

    private OSSClient getOSSClient() {
        OSSClient ossClient = (OSSClient) this.ossClientContext.get();
        if (ossClient == null) {
            this.ossClientContext.set(new OSSClient(this.ossConfig.getEndpoint(), this.ossConfig.getAccessKeyId(), this.ossConfig.getAccessKeySecret()));
        }

        return (OSSClient) this.ossClientContext.get();
    }

    private void closeOSSClient() {
        OSSClient ossClient = (OSSClient) this.ossClientContext.get();
        this.ossClientContext.remove();
        if (ossClient != null) {
            ossClient.shutdown();
        }

    }

    protected <R, T> T invoke(R operationRequest, OSSFunction<R, T> ossFunction) {
        Object var3;
        try {
            var3 = this.invoke0(operationRequest, ossFunction);
        } catch (Throwable var7) {
            throw new RuntimeException(var7);
        } finally {
            this.closeOSSClient();
        }

        return (T) var3;
    }

    private <R, T> T invoke0(R operationRequest, OSSFunction<R, T> ossFunction) throws Throwable {
        return ossFunction.apply(operationRequest, this.getOSSClient());
    }

    interface OSSFunction<R, T> {
        T apply(R var1, OSSClient var2) throws Throwable;
    }
}
